package service

import (
	"context"

	v2 "Cosmos.Communication/api/v2"
	"Cosmos.Communication/internal/biz"
	"github.com/go-kratos/kratos/v2/log"
	"google.golang.org/protobuf/types/known/anypb"
	"google.golang.org/protobuf/types/known/wrapperspb"
)

type DataSetService struct {
	v2.UnimplementedRpcDataSetServiceServer
	responbility Responsibility
	logHelper    *log.Helper
}

func NewDataSetService(responbility Responsibility, logger log.Logger) *DataSetService {
	return &DataSetService{responbility: responbility, logHelper: log.NewHelper(logger)}
}

func (d *DataSetService) Query(ctx context.Context, req *v2.RpcDataQueryRequest) (result *v2.RpcResult, err error) {
	result = &v2.RpcResult{
		Code: 200,
	}
	if req == nil {
		result.Code = 400
		return
	}

	callReq := &biz.DataQueryRequest{
		Type:       req.Type.GetValue(),
		Parameters: req.Param.GetValue(),
	}
	callResult, err := d.responbility.Query(ctx, callReq)
	if err != nil {
		result.Code = 500
		result.Message = &wrapperspb.StringValue{Value: err.Error()}
		return
	}
	if callResult == nil {
		result.Code = 500
		result.Message = &wrapperspb.StringValue{Value: "Query result is nil"}
		return
	}
	if callResult.Code != 200 {
		result.Code = int32(callResult.Code)
		result.Message = &wrapperspb.StringValue{Value: callResult.Message}
		return
	}

	response := &v2.RpcDataQueryResponse{}
	if callResult.Data != nil {
		response.Data = &wrapperspb.StringValue{Value: callResult.Data.Data}
	}
	if result.Data, err = anypb.New(response); err != nil {
		return
	}
	return
}
func (d *DataSetService) Subscrib(ctx context.Context, req *v2.RpcDataSubscribeRequest) (result *v2.RpcResult, err error) {
	result = &v2.RpcResult{
		Code: 200,
	}

	if req == nil {
		result.Code = 400
		d.logHelper.Info("Subscrib_Processor request is nil")
		return
	}

	d.logHelper.Info("Subscrib_Processor param", req.Param, req.Type)

	callReq := &biz.DataSubscribeRequest{
		Type:       req.Type.GetValue(),
		Parameters: req.Param.GetValue(),
	}
	callResult, err := d.responbility.Subscribe(ctx, callReq)
	if err != nil {
		result.Code = 500
		result.Message = &wrapperspb.StringValue{Value: err.Error()}
		d.logHelper.Info("Subscrib_Processor err:", err)
		return
	}
	if callResult == nil {
		result.Code = 500
		result.Message = &wrapperspb.StringValue{Value: "Subscrib result is nil"}
		return
	}
	if callResult.Code != 200 {
		result.Code = int32(callResult.Code)
		result.Message = &wrapperspb.StringValue{Value: callResult.Message}
		return
	}

	response := &v2.RpcDataSubscribeResponse{}
	if callResult.Data != nil {
		response.Id = &wrapperspb.StringValue{Value: callResult.Data.Id}
	}
	if result.Data, err = anypb.New(response); err != nil {
		return
	}
	return
}
func (d *DataSetService) UnSubscrib(ctx context.Context, req *v2.RpcDataUnsubscribeRequest) (result *v2.RpcResult, err error) {
	result = &v2.RpcResult{
		Code: 200,
	}
	if req == nil {
		result.Code = 400
		return
	}

	callReq := &biz.DataUnsubscribeRequest{
		Id: req.Id.GetValue(),
	}
	callResult, err := d.responbility.Unsubscribe(ctx, callReq)
	if err != nil {
		result.Code = 500
		result.Message = &wrapperspb.StringValue{Value: err.Error()}
		return
	}
	if callResult == nil {
		result.Code = 500
		result.Message = &wrapperspb.StringValue{Value: "UnSubscrib result is nil"}
		return
	}
	if callResult.Code != 200 {
		result.Code = int32(callResult.Code)
		result.Message = &wrapperspb.StringValue{Value: callResult.Message}
		return
	}

	return
}
func (d *DataSetService) Push(req *v2.RpcPushRequest, srv v2.RpcDataSetService_PushServer) (err error) {
	for {

		var message = d.responbility.Poll()
		if message == nil {
			continue
		}

		result := &v2.RpcResult{
			Code: 200,
		}
		response := &v2.RpcPushResponse{}
		rpcData := &v2.RpcData{Value: &wrapperspb.StringValue{Value: message.Value}}
		for _, item := range message.Ids {
			rpcData.Ids = append(rpcData.Ids, &wrapperspb.StringValue{Value: item})
		}
		response.Data = append(response.Data, rpcData)
		if result.Data, err = anypb.New(response); err != nil {

			d.logHelper.Error("Push Parse Error:", err.Error())
			continue
		}

		if err = srv.Send(result); err != nil {
			d.logHelper.Error("Push Send Error:", err.Error())
			return
		}
	}
}
